// 核心模块
const gulp = require('gulp');
// less
const less = require('gulp-less');
// 压缩工具
const connect = require('gulp-connect');
// 引入html
const contentIncluder = require('gulp-content-includer');
// 压缩html
const htmlmin = require('gulp-htmlmin');
// 压缩js
const uglify = require('gulp-uglify');
// 压缩css
const minifycss = require('gulp-minify-css');
// 文件系统
const fs = require('fs');
// 颜色输出
const color = require('gulp-color');
// sass
const sass = require("gulp-sass");
// filter
const filter = require('gulp-filter');
// 执行系统cmd命令
const exec = require('child_process').exec;
// 语法检测
const eslint = require('gulp-eslint');
// browserSync
const browserSync = require("browser-sync").create('bs_server');
// js语法检索结果
var eslintResults = [];

// default config
var config = {
  src: 'src',
  dev: 'dev',
  dist: 'dist',
  filter: ['/block'],
  specialFiles: [],
  outColor: {
    renamed: 'GREEN',
    changed: 'YELLOW',
    deleted: 'RED',
    added: 'GREEN'
  }
}

// 默认执行开发模式
gulp.task('default', ['outlogo', 'readConfig', 'cleardist', 'serve']);

// 执行开发模式
gulp.task('bulid', ['outlogo', 'readConfig'], function() {
  // tools.start('bulid');
});

/*打印logo*/
gulp.task('outlogo', function() {
  console.log('\n-------------------------------------');
  console.log('qie.suwis.com');
  console.log('-------------------------------------\n');
});

// 读取配置文件
gulp.task('readConfig', function(cb) {
  var _this = this;
  //读取配置文件
  fs.readFile('config.json', function(err, data) {
    var conf = JSON.parse(data.toString());
    for (var f in conf) {
      if (typeof(conf.f) === 'object') {
        for (var k in conf.f) {
          config[f][k] = conf[f][k];
        }
      } else {
        config[f] = conf[f];
      }
    }
    console.log('[suwis] config loading finished');
    //开始后面的操作
    cb();
  });
});

// 清空dist文件夹
gulp.task('cleardist', ['readConfig'], function() {
  try {
    exec('del/f/s/q ' + config.dist.replace(/\//g, '\\'), function(err, out) {
      console.log('[suwis] clear dist finished');
    });
  } catch (e) {}
})

// 处理各种文件的工具
const tools = {
  deletefile: function(path) {
    if (path == null) return;
    // 同步删除文件
    fs.unlink(path, function(err) {
      if (err) console.log(color(err.error, config.deletedcolor));
    });
  },
  // 转换到对应编译出来的文件夹路径(带文件名)
  transitionPath: function(path) {
    if (!path) return null;
    path = path.substring(path.indexOf(config.src), path.length);
    path = path.substring(path.indexOf('\\'), path.length);
    path = config.dist + path;
    return path;
  },
  // 转换到对应编译出来的文件夹路径
  transitionFolder: function(path) {
    if (!path) return null;
    path = path.substring(path.indexOf(config.src), path.length);
    path = path.substring(path.indexOf('\\'), path.length);
    path = config.dist + path;
    //去掉最后的文件名
    path = path.substring(0, path.lastIndexOf('\\'));
    return path;
  },
  // 输出eslint校验结果
  eslintNotify: function(rs) {
    var errorlist = '';
    for (var f in rs) {
      if (rs[f].errorCount > 0) {
        for (var k in rs[f].messages) {
          errorlist += `
          <dl>
            <dt>文件：${rs[f].filePath}</dt>
            <dd>校验的规则id：${rs[f].messages[k].ruleId}</dd>
            <dd>严重程度：${rs[f].messages[k].severity}级</dd>
            <dd>类型：${rs[f].messages[k].nodeType}</dd>
            <dd>描述：${rs[f].messages[k].message}</dd>
            <dd>位置：第${rs[f].messages[k].line}行，第${rs[f].messages[k].column}列</dd>
            <dd>错误片段：${rs[f].messages[k].source}</dd>
          </dl>
          `;
        }
      }
    }
    // 判断是否有错
    if (errorlist === '') return;
    rs = JSON.stringify(rs);
    var tpl = `<style>
        body {
          overflow: hidden;
        }
        #__bs_notify__ {
          background: transparent !important;
        }
        #__bs_notify_msgwrap__ {
          position: fixed;
          width: 100%;
          height: 100%;
          top: 0px;
          left: 0px;
          font-family: Microsoft YaHei;
          background: rgba(0, 0, 0, 0.8);
          box-sizing: border-box;
          padding: 10px;
          text-align: left;
          font-size: 13px;
          line-height: 20px;
          overflow-y: scroll;
        }
        #__bs_notify_msgwrap__ dl{
          border-bottom: 1px solid #902222;
          padding-bottom: 10px;
          margin-bottom: 10px;
          color: #ba1f1f;
        }
        #__bs_notify_msgwrap__ dl dt,#__bs_notify_msgwrap__ dl dd{
          font-weight: normal;
          line-height: 22px;
        }
    </style>
    <div id="__bs_notify_msgwrap__">${errorlist}</div>`;
    // 向浏览器端发送消息
    browserSync.notify(tpl, 1000000);
  },
  html: {
    update: function(paths, target) {
      if (!paths) return;
      return gulp.src(paths)
        .pipe(contentIncluder({
          includerReg: /<!\-\-include\s+"([^"]+)"\-\->/g
        }))
        // .pipe(filter(config.filter, {
        //     restore: true
        // }))
        .pipe(gulp.dest(target));
    }
  },
  css: {
    update: function(paths, target) {
      if (!paths) return;
      return gulp.src(paths)
        .pipe(minifycss())
        .pipe(gulp.dest(target));
    }
  },
  scss: {
    update: function(paths, target) {
      if (!paths) return;
      return gulp.src(paths)
        .pipe(sass())
        .pipe(gulp.dest(target));
    }
  },
  js: {
    update: function(paths, target) {
      if (!paths) return;
      return gulp.src(paths)
        .pipe(eslint())
        .pipe(uglify())
        .pipe(eslint.results(results => {
          // Called once for all ESLint results.
          console.log(`Total Results: ${results.length}`);
          console.log(`Total Warnings: ${results.warningCount}`);
          console.log(`Total Errors: ${results.errorCount}`);
          eslintResults = results;
          setTimeout(function() {
            tools.eslintNotify(eslintResults);
          }, 500);
        }))
        .pipe(gulp.dest(target));
    }
  },
  img: {
    update: function(paths, target) {
      if (!paths) return;
      return gulp.src(paths)
        .pipe(gulp.dest(target));
    }
  },
  media: {
    update: function(paths, target) {
      if (!paths) return;
      return gulp.src(paths)
        .pipe(gulp.dest(target));
    }
  },
  specialFiles: {
    update: function(paths, target) {
      if (!paths) return;
      return gulp.src(paths)
        .pipe(gulp.dest(target));
    }
  }
}

// 处理全部的html文件
gulp.task('html', ['readConfig'], function() {
  return tools.html.update([
    config.src + '/**/*.html',
    config.src + '/**/*.htm',
    config.src + '/**/*.shtml'
  ], config.dist);
});

// 处理全部的js文件
gulp.task('js', ['readConfig'], function() {
  return tools.js.update(config.src + '/**/*.js', config.dist);
});

// 处理全部的scss文件
gulp.task('scss', ['readConfig'], function() {
  return tools.scss.update(config.src + '/**/*.scss', config.dist);
});

// 处理全部的css文件
gulp.task('css', ['readConfig'], function() {
  return tools.css.update(config.src + '/**/*.css', config.dist);
});

// 处理全部的img文件
gulp.task('img', ['readConfig'], function() {
  return tools.img.update([
    config.src + '/**/*.jpg',
    config.src + '/**/*.jpeg',
    config.src + '/**/*.png',
    config.src + '/**/*.gif',
    config.src + '/**/*.svg',
    config.src + '/**/*.webp'
  ], config.dist);
});

// 处理全部的media文件
gulp.task('media', ['readConfig'], function() {
  return tools.media.update([
    config.src + '/**/*.mp4',
    config.src + '/**/*.mpeg4',
    config.src + '/**/*.ogg',
    config.src + '/**/*.webm',
    config.src + '/**/*.mp3',
  ], config.dist);
});

// 拷贝特殊文件
gulp.task('specialFiles', ['readConfig'], function() {
  if (config.specialFiles.length == 0) return;
  return tools.specialFiles.update(config.specialFiles, config.dist);
});

// 监听html变化
gulp.watch([
  config.src + '/**/*.html',
  config.src + '/**/*.htm',
  config.src + '/**/*.shtml'
], function(event) {
  console.log(color('[suwis] ' + event.path + ' was ' + event.type, config.outColor[event.type]));
  switch (event.type) {
    case 'changed':
      tools.html.update(event.path, tools.transitionFolder(event.path));
      break;
    case 'renamed':
      tools.html.update(event.path, tools.transitionFolder(event.path));
      break;
    case 'deleted':
      tools.deletefile(tools.transitionPath(event.path));
      break;
    case 'added':
      tools.html.update(event.path, tools.transitionFolder(event.path));
      break;
    default:

  }
});

// 监听css变化
gulp.watch([config.src + '/**/*.css'], function(event) {
  console.log(color('[suwis] ' + event.path + ' was ' + event.type, config.outColor[event.type]));
  switch (event.type) {
    case 'changed':
      tools.css.update(event.path, tools.transitionFolder(event.path));
      break;
    case 'renamed':
      tools.css.update(event.path, tools.transitionFolder(event.path));
      break;
    case 'deleted':
      tools.deletefile(tools.transitionPath(event.path));
      break;
    case 'added':
      tools.css.update(event.path, tools.transitionFolder(event.path));
      break;
    default:

  }
});

// 监听scss变化
gulp.watch([config.src + '/**/*.scss'], function(event) {
  console.log(color('[suwis] ' + event.path + ' was ' + event.type, config.outColor[event.type]));
  switch (event.type) {
    case 'changed':
      tools.scss.update(event.path, tools.transitionFolder(event.path));
      break;
    case 'renamed':
      tools.scss.update(event.path, tools.transitionFolder(event.path));
      break;
    case 'deleted':
      tools.deletefile(tools.transitionPath(event.path));
      break;
    case 'added':
      tools.scss.update(event.path, tools.transitionFolder(event.path));
      break;
    default:

  }
});

// 监听js变化
gulp.watch([config.src + '/**/*.js'], function(event) {
  console.log(color('[suwis] ' + event.path + ' was ' + event.type, config.outColor[event.type]));
  switch (event.type) {
    case 'changed':
      tools.js.update(event.path, tools.transitionFolder(event.path));
      break;
    case 'renamed':
      tools.js.update(event.path, tools.transitionFolder(event.path));
      break;
    case 'deleted':
      tools.deletefile(tools.transitionPath(event.path));
      break;
    case 'added':
      tools.js.update(event.path, tools.transitionFolder(event.path));
      break;
    default:

  }
});

// 监听img变化
gulp.watch([
  config.src + '/**/*.jpg',
  config.src + '/**/*.jpeg',
  config.src + '/**/*.png',
  config.src + '/**/*.gif',
  config.src + '/**/*.svg',
  config.src + '/**/*.webp'
], function(event) {
  console.log(color('[suwis] ' + event.path + ' was ' + event.type, config.outColor[event.type]));
  switch (event.type) {
    case 'changed':
      tools.img.update(event.path, tools.transitionFolder(event.path));
      break;
    case 'renamed':
      tools.img.update(event.path, tools.transitionFolder(event.path));
      break;
    case 'deleted':
      tools.deletefile(tools.transitionPath(event.path));
      break;
    case 'added':
      tools.img.update(event.path, tools.transitionFolder(event.path));
      break;
    default:

  }
});

// 使用默认任务启动Browsersync，监听JS文件
gulp.task('serve', ['readConfig', 'html', 'js', 'css', 'scss', 'img', 'media'], function() {
  // 从这个项目的根目录启动服务器
  browserSync.init({
    server: {
      baseDir: config.dist
    },
    // 更改默认端口
    ui: {
      port: 8088
    },
    // 监听局部刷新的文件
    files: [
      config.src + '/**/*.css',
      config.src + '/**/*.js',
      config.src + '/**/*.jpg',
      config.src + '/**/*.jpeg',
      config.src + '/**/*.png',
      config.src + '/**/*.gif',
      config.src + '/**/*.svg',
      config.src + '/**/*.webp'
    ], //而忽略某些路径
    snippetOptions: {
      //忽略Templates文件夹中的所有HTML文件
      ignorePaths: "block/*.html",
      //提供一个自定义的正则表达式插入片段。
      rule: {
        match: /<\/body>/i,
        fn: function(snippet, match) {
          return snippet + match;
        }
      }
    }
  }, function() {
    // 服务器初始化完成后输出js校验结果
    setTimeout(function() {
      tools.eslintNotify(eslintResults);
    }, 1600);
  });
  // 开启监视
  gulp.watch([config.src + '/**/*.html'], function(event) {
    browserSync.reload();
  });
});
